package com.java.cg.seckill.timer;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.java.cg.seckill.dao.SeckillGoodsDao;
import com.java.cg.seckill.entity.SeckillGoods;
import com.java.cg.seckill.utils.DateUtil;
import com.java.common.constants.CacheKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * 定时任务 spring task(多线程)
 * 1.开始spring task
 * 2.在执行的方法上修饰一个注解  注解中指定何时执行即可
 */
@Component
public class SeckillGoodsPushTask {
	@Autowired
	private SeckillGoodsDao seckillGoodsDao;
	@Autowired
	private RedisTemplate redisTemplate;

	//反复被执行的方法 隔5秒钟执行一次
	@Scheduled(cron = "0/5 * * * * ?")
	public void loadGoodsToRedis() {
		//1.获取当前的时间对应的5个秒杀时间段 14:00-16:00 16:00-18:00 ...
		List<Date> dateMenus = DateUtil.getDateMenus();
		//2.循环遍历5个时间段 获取到时间的日期
		for (Date starttime : dateMenus) {
			//2019090516
			String extName = DateUtil.data2str(starttime, DateUtil.PATTERN_YYYYMMDDHH);
			//3.将循环到的时间段 作为条件 从数据库中执行查询 得出数据集
			/**
			 * select * from tb_seckill_goods where
			 stock_count>0
			 and `status`='1'
			 and start_time >= 开始时间段
			 and end_time < 开始时间段+2hour  and id  not in (redis中已有的id)
			 */
			//查询出redis已经存在的秒杀商品
			Set keys = redisTemplate.boundHashOps(CacheKey.SEC_KILL_GOODS_PREFIX + extName).keys();

			List<SeckillGoods> seckillGoods = seckillGoodsDao.selectList(new LambdaQueryWrapper<SeckillGoods>()
					.eq(SeckillGoods::getStatus, "1").gt(SeckillGoods::getStockCount, 0)
					.ge(SeckillGoods::getStartTime, starttime).lt(SeckillGoods::getEndTime, (DateUtil.addDateHour(starttime, 2)))
					.notIn(CollectionUtil.isNotEmpty(keys), SeckillGoods::getId, keys));//redis中已有的商品不能添加 即排除掉redis已有的商品

			//4.将数据集存储到redis中(key field value的数据格式 )
			//key(时间段:2019090516)     field (id:1)   value(商品的数据pojo)
			for (SeckillGoods seckillGood : seckillGoods) {
				redisTemplate.boundHashOps(CacheKey.SEC_KILL_GOODS_PREFIX + extName).put(seckillGood.getId(), seckillGood);
				//设置有效期
				redisTemplate.expireAt(CacheKey.SEC_KILL_GOODS_PREFIX + extName, DateUtil.addDateHour(starttime, 2));

				//添加一个计数器 (key:商品的ID  value : 库存数)
				redisTemplate.boundHashOps(CacheKey.SECK_KILL_GOODS_COUNT_KEY).increment(seckillGood.getId(),seckillGood.getStockCount());
			}
		}
	}

	private void pushGoods(SeckillGoods seckillGoods) {
		//创建redis的队列(每一种商品就是一个队列,队列的元素的个数和商品的库存一致) 压入队列
		for (Integer i = 0; i < seckillGoods.getStockCount(); i++) {//5
			redisTemplate.boundListOps(CacheKey.SEC_KILL_CHAOMAI_LIST_KEY_PREFIX + seckillGoods.getId()).leftPush(seckillGoods.getId());
		}
	}
}
